import axios, {
  AxiosInstance,
  AxiosRequestConfig,
  AxiosResponse,
  AxiosError,
} from 'axios';

import { ElMessage } from "element-plus";
import { useUserStore } from "@/store/modules/user"; // 引入vuex方法
import { useRouter } from "vue-router";
import router from "@/router";
let isSx = false;
const service = axios.create({
  baseURL: import.meta.env.VITE_BASE_API, // url = base url + request url
  // withCredentials: true, //
  timeout: 25000, // 超时实际
});

// 是否正在刷新
let isRefreshing = false;
// 存储请求的数组
let cacheRequestArr: Function[] = [];

// 无法换到token后的过期方法
const loginOut = () => {
  const userStore = useUserStore();
  userStore.loginOut();

  router.replace("/login");
};

// 换完token后，把并发的请求 继续开始
const afreshRequest = (token: string) => {
  cacheRequestArr.map((cb) => cb(token));
  cacheRequestArr = [];
  console.log("循环加载完成");
  isSx = true;
};
const refreshRequest = (config: AxiosRequestConfig) => {
  let retry = new Promise((resolve) => {
    cacheRequestArr.push((token: string) => {
      config!.headers!["Authorization"] = "Bearer " + token;
      // 将请求挂起
      resolve(config);
    });
  });
  return retry;
};

// 核心方法
const refreshToken = (config: AxiosRequestConfig) => {
  if (isRefreshing) {
    console.log("已经在加载了");
    return refreshRequest(config);
  } else {
    console.log("开始刷新token");
    isRefreshing = true;
    // 刷新token的方法，自己整下吧，我的是放pinia 里面，顺便调用完把token之类的换了
    const userStore = useUserStore();
    userStore
      .refreshToken()
      .then((res) => {
        let token = userStore.getToken;
        afreshRequest(token!);
      })
      .catch(() => {
        //  ElMessage.error("登录过期");
        loginOut();
      })
      .finally(() => {
        isRefreshing = false;
      });
    // 把当前请求也加入进去
    return refreshRequest(config);
  }
};

interface AxiosRequestConfigFace extends  AxiosRequestConfig {
  noToken?: boolean;
}

service.interceptors.request.use(
  (config: AxiosRequestConfigFace) => {
    const userStore = useUserStore();
    let token = userStore.getToken;
    if (token && !config.noToken) {
      config!.headers!["Authorization"] = "Bearer " + token;
      const expiresAt = userStore.getTokenExpiresAt;
      const time = new Date().valueOf();
      const residueTime = (expiresAt - time) / 1000; // 剩余时间
      console.log("剩余时间" + residueTime);
      if (
        residueTime &&
        residueTime < 300 &&
        !config.url.includes("/hnvmns-auth/oauth2/token")
      ) {
        console.log("重新获取token");
        return refreshToken(config);
      }
    }
    return config;
  },
  (error: AxiosError) => {
    console.log(error);
    return Promise.reject(error);
  }
);

service.interceptors.response.use(
  async (response: AxiosResponse<any>) => {
    const res = response.data;
    const config=response.config

    if (Object.prototype.toString.call(res) == "[object Blob]" || config.noVerify!) {
      console.log("下载开始");
      return res;
    } else if (res.code === 200) {
      return res;
    } else {
      if (res.errorCode === 401) {
        console.log("401");
        loginOut();
        return;
      } else {
        ElMessage.error(res.description);
      }
      return Promise.reject(res);
    }
  },
  (error) => {
    console.log(error);
    if (error && error.response && error.response.status == 401) {
      console.log("登录过期");
      loginOut();
      return;
    } else if (error.message.includes("authentication")) {
      // 如果包含没有携带 authentication 权限
      // 很大概率是同时多个请求，第一个已经过期清除了 token，所以第二个就不要再提示了
    } else {
      ElMessage({
        message: error.message.includes("timeout")
          ? "网络延迟,请稍后再试!"
          : error.message.includes("404")
          ? "接口没找到"
          : error.message,
        type: "error",
        duration: 5 * 1000,
      });
    }
    return Promise.reject(error);
  }
);

export default service;
